package com.wanmait.server.Shiro;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.wanmait.common.util.Constant;
import com.wanmait.model.entity.Permissions;
import com.wanmait.model.entity.Staff;
import com.wanmait.model.mapper.StaffMapper;
import com.wanmait.server.service.PermissionsService;
import com.wanmait.server.util.ShiroUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @ClassName UserRealm
 * @Author 羽
 * @Date 2020/12/10 22:35
 * @Version 1.0
 **/
@Component
public class UserRealm extends AuthorizingRealm {

    //日志
    private static final Logger log = LoggerFactory.getLogger(UserRealm.class);

    //获得用户对象
    @Autowired
    private StaffMapper staffMapper;

    @Autowired
    private PermissionsService permissionsService;

    /**
    * TODO
    * @author 羽
    * @date 2020/12/10 22:52
    *用户授权
     * 资源-权限分配 ~ 授权 ~ 需要将分配给当前用户的权限列表塞给shiro的权限字段中去
    **/
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //获取当前登录用户（主体）
        Staff staff= (Staff) principals.getPrimaryPrincipal();
        //获取登录用户的id
        Integer id = staff.getId();

        List<String> perms= Lists.newLinkedList();
        //系统超级管理员拥有最高的权限，不需要发出sql的查询，直接拥有所有权限；否则，则需要根据当前用户id去查询权限列表
        if ((long)id ==  Constant.SUPER_ADMIN){
            List<Permissions> list= permissionsService.list();
            if (list!=null && !list.isEmpty()){
                perms=list.stream().map(Permissions::getPerms).collect(Collectors.toList());
            }
        }else{
            perms=staffMapper.queryAllPerms(id);
        }

        //对于每一个授权编码进行 , 的解析拆分
        Set<String> stringPermissions= Sets.newHashSet();
        if (perms!=null && !perms.isEmpty()){
            for (String p:perms){
                if (StringUtils.isNotBlank(p)){
                    stringPermissions.addAll(Arrays.asList(StringUtils.split(p.trim(),",")));
                }
            }
        }
        System.out.println("对于每一个授权编码进行 , 的解析拆分"+stringPermissions.toString());
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.setStringPermissions(stringPermissions);
        return info;
    }

    /**
    * TODO
    * @author 羽
    * @date 2020/12/10 22:52
    *用户的登陆认证
    **/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        final String username = token.getUsername();
        final String password = String.valueOf(token.getPassword());
        log.info("这里是登陆认证：用户名{}   密码{}",username,password);
        //查询包装器
        Staff staff = staffMapper.selectOne(new QueryWrapper<Staff>().eq("job_number",username));
        if(staff==null){
            System.out.println("该账户不存在");
            throw new UnknownAccountException("该账户不存在");
        }
        //当用户停用时
        if(!staff.getState()){
            System.out.println("该账户已经停用");
            throw new DisabledAccountException("该账户已经停用");
        }

        //另外一种验证逻辑
        /*String realPassword=ShiroUtil.sha256(password,staff.getSalt());
        if (StringUtils.isBlank(realPassword) || !realPassword.equals(staff.getPassword())){
            throw new IncorrectCredentialsException("账户密码不匹配!");
        }
        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(staff,password,getName());
        */
        //将用户名密码的逻辑讲给密码匹配器
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(staff,staff.getPassword(), ByteSource.Util.bytes(staff.getSalt()),getName());

        return info;
    }
    /**
    * TODO
    * @author 羽
    * @date 2020/12/11 11:03
    * 密码匹配器
    **/
    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        HashedCredentialsMatcher shaCredentialsMatcher = new HashedCredentialsMatcher();
        shaCredentialsMatcher.setHashAlgorithmName(ShiroUtil.hashAlgorithmName);
        shaCredentialsMatcher.setHashIterations(ShiroUtil.hashIterations);
        super.setCredentialsMatcher(shaCredentialsMatcher);
    }



}
